package clubhouse.communication;

import java.io.IOException;

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import clubhouse.communication.SerialComm;
import clubhouse.motioncommand.MotionCommand;
import clubhouse.motioncommand.NodeControl;

/**
 * @author Anis Darwich & Lionel Croix - Simulation and experimentation on Robot in WSN - WnSN Lab - SJTU
 */
public class RobotCommunication extends SerialComm implements Runnable{

	/**Object used to display logs in message log panel.*/
	private final static Logger log = Logger.getLogger(RobotCommunication.class);

	/**Sleeping delay.*/
	private final int delay = 0;
	/**The used COM port.*/
	public static final String COM = "COM11";
	
	/**The current packet.*/
	private String packet = null;

	/**Reception queue.*/
	private ReceptionFifo rx;
	/**Transmission queue.*/
	private TransmissionFifo tx;
	
	/**
	 * Constructs the RobotCommunication objects according to specified reception and transmission queues.
	 * @param reception reception queue object.
	 * @param transmission reception queue object.
	 * @throws Exception if an error occur during the opening of serial port.
	 */
	public RobotCommunication(ReceptionFifo reception, TransmissionFifo transmission) throws Exception {
		super();
		this.openSerialPort(RobotCommunication.COM, 9600);
		this.rx = reception;
		this.tx = transmission;
		PropertyConfigurator.configure("log4j.properties");
		//this.run();
	}
	

	
	/**
	 * Sends on the UART interface the first element in the transmission fifo.
	 */
	public void sendMotionCommand () {
		MotionCommand tosend = tx.getMotionCom();
		if (tosend != null) {
			try {
				this.sendCommand(tosend.toSend());
			} catch (IOException e) {
				log.debug("RobotCommunication: could not send motion command");
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Reset the variable containing the last received message.
	 */
	public void resetReveivedMessage() {
		this.resetLastResponse();
	}
	
	/** See following "See Also".
	 * @see clubhouse.communication.SerialComm#getLock()
	 */
	protected Object getLock() {
		return this;
	}
	
	/** See following "See Also".
	 * @see java.lang.Runnable#run()
	 */
	public void run() {
		log.debug("RobotCommunication: thread [" + Thread.currentThread().getName() + "]");
		try {
			while (true) {
				synchronized(this.getLock()) {
					
					//Send motion command if available
					this.sendMotionCommand ();
					
					this.packet = this.getLastResponse();
					this.resetReveivedMessage();
					//Parse and store packet
					if (this.packet != null) {
						switch (Integer.parseInt(packet.substring(2, 4), 16)) {
						case 1:
							NodeControl nodepacket = NodeControl.parse(this.packet);
							//log.debug("Received node control: "+ nodepacket.toHexPrint() +"\n");
							this.rx.rxNodeMeasurement(nodepacket);
							break;
						case 17:
							MotionCommand motionAck = MotionCommand.parse(this.packet);
							//log.debug("Received motion ack: "+ motionAck.toHexPrint() +"\n");
							this.rx.rxMotionAck(motionAck);
							break;
						default:
							log.debug("Received unknown message type\n");
							break;
						}
					}
				}
				//log.debug("RobotCommunication: thread [" + Thread.currentThread().getName() + "] going to sleep "+ delay +" ms\n");
				Thread.sleep(delay);
			}
		} catch (Throwable th) {
			th.printStackTrace();
		}
	}
}
